/**
 * Copyright [2012-2013] [Guðmundur Björn Birkisson]
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. Copyright [2012-2013] [Guðmundur Björn Birkisson]
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * ---------------------------------------------------------------------------
 * 
 * Flex definition file for tokenization.
 * 
 */

package karel.lang;

%%

%{
    private RDParser yyparser;
    private StringBuffer morphoBuffer;
    private StringBuffer stringBuf;

    public Yylex(java.io.Reader r, RDParser yyparser) {
        this(r);
        this.yyparser = yyparser;
        this.morphoBuffer = new StringBuffer();
        this.stringBuf = new StringBuffer();
    }

    public String getMorphoBuffer() {
        return morphoBuffer.toString();
    }

    public int getLine() {
        return yyline;
    }

    public int getColumn() {
        return yycolumn;
    }
%}

%eofval{
{ return Yytoken.EOF; }
%eofval}
%column
%line
%public
%unicode

/* ---------- START Syntax highlighting sync ---------- */

NL  = \n | \r | \r\n
WHITESPACE = [ \t]+

COMMENT = "##" [^\r\n]*

MLCOMMENTSTART = "#{"
MLCOMMENTSTOP = "}#"

//STARTMORPHO = "&morpho"
//STOPMORPHO = "&morpho"

NAME = [:jletter:] [:jletterdigit:]*

DIGIT = [0-9]+
INT = {DIGIT}
DOUBLE = {DIGIT} ("." {DIGIT})? (("e"|"E")("+"|"-")?{DIGIT})?
//STRING = (\" ( [^\"\n\\] | \\[^\n] )* (\n | \\\n | \"))

//%state MORPHO
%state MLCOMMENT
%state STRING

%%
<YYINITIAL> {

/* keywords */
    "stef"      {   yyparser.yylval = yytext(); return Yytoken.FUNC; }
    "breyta"    {   yyparser.yylval = yytext(); return Yytoken.VAR; }
    "ef"        {   yyparser.yylval = yytext(); return Yytoken.IF; }
    "annars"    {   yyparser.yylval = yytext(); return Yytoken.ELSE; }
    "annars ef" {   yyparser.yylval = yytext(); return Yytoken.ELSEIF; }
    "me\u00F0an" {   yyparser.yylval = yytext(); return Yytoken.WHILE; }
    "endurtaka" {   yyparser.yylval = yytext(); return Yytoken.REPEAT; }
    "skila"     {   yyparser.yylval = yytext(); return Yytoken.RETURN; }
    "satt"      { yyparser.yylval = yytext(); return Yytoken.TRUE; }
    "\u00F3satt"     { yyparser.yylval = yytext(); return Yytoken.FALSE; }

/* program operators */
    "=="    {   yyparser.yylval = yytext(); return Yytoken.EQ; }
    ">="    {   yyparser.yylval = yytext(); return Yytoken.GE; }
    "<="    {   yyparser.yylval = yytext(); return Yytoken.LE; }
    "!"     {   yyparser.yylval = yytext(); return Yytoken.NOT; }
    "ekki"     {   yyparser.yylval = yytext(); return Yytoken.NOT; }
    "!="    {   yyparser.yylval = yytext(); return Yytoken.NE; }
    "||"    {   yyparser.yylval = yytext(); return Yytoken.OR; }
    "e\u00F0a"    {   yyparser.yylval = yytext(); return Yytoken.OR; }
    "&&"    {   yyparser.yylval = yytext(); return Yytoken.AND; }
    "og"    {   yyparser.yylval = yytext(); return Yytoken.AND; }
    "{"     {   yyparser.yylval = yytext(); return Yytoken.BRACETOPEN; }
    "}"     {   yyparser.yylval = yytext(); return Yytoken.BRACKETCLOSE; }
    "("     {   yyparser.yylval = yytext(); return Yytoken.PARAOPEN; }
    ")"     {   yyparser.yylval = yytext(); return Yytoken.PARACLOSE; }

    "=" |
    "," |
    "+" | 
    "-" | 
    "*" | 
    "/" |
    "%" | 
    "^" |
    ">" |
    "<"     {   yyparser.yylval = yytext();
                return Yytoken.OP; }
    
    

/* names   */
    {NAME}  {
                yyparser.yylval = yytext();
                return Yytoken.NAME;
            }    

/* literals */
    {INT}   {
                yyparser.yylval = yytext();
                return Yytoken.INT;
            }
            
    {DOUBLE} {
                yyparser.yylval = yytext();
                return Yytoken.DOUBLE;
            }

    \" {
                stringBuf.setLength(0);
                stringBuf.append("\"");
                yybegin(STRING);
            }

/* other */
/*
    {STARTMORPHO} { morphoBuffer.setLength(0);
                    yybegin(MORPHO); 
                    return Yytoken.STARTMORPHO; }
*/

    {MLCOMMENTSTART} { yybegin(MLCOMMENT); }

    {WHITESPACE} { }

    {COMMENT}       {}

}

<STRING> {
    \"    {     yybegin(YYINITIAL);
                stringBuf.append("\"");
                yyparser.yylval = stringBuf.toString(); 
                return Yytoken.STRING; }
    
    [^\r\n\"\\]+ { stringBuf.append(yytext()); }

    \\\"         { stringBuf.append("\\\""); }
    \\\\         { stringBuf.append("\\\\"); }
    \\n          { stringBuf.append("\n"); }
    \\r          { stringBuf.append("\r"); }
    \\t          { stringBuf.append("\t"); }
    \\b          { stringBuf.append("\b"); }
    \\f          { stringBuf.append("\b"); }

    [\\.]        { yyparser.error("Táknið '\\' má ekki vera eitt og sér í streng. Notaðu '\\\\'.",yytext().length()); }
    {NL}         { yyparser.error("Byrjun og endir á streng þarf að vera í sömu línu!",1); }
}

<MLCOMMENT> {
    {MLCOMMENTSTOP} {   yybegin(YYINITIAL); }
    .               {   }
    {NL}            {   }
}

/*
<MORPHO> {
    {STOPMORPHO}    {   yybegin(YYINITIAL); 
                        return Yytoken.STOPMORPHO;}

    .               {   morphoBuffer.append( yytext() ); }
    {NL}            {   morphoBuffer.append( yytext() ); 
                        }
}
*/

/* ---------- STOP Syntax highlighting sync ---------- */

/* newline */
<YYINITIAL>    {NL}  {  return Yytoken.NL;  }

/* error fallback */
<YYINITIAL>   [^]    { yyparser.error("Óþekkt tákn '"+yytext()+"'",yytext().length()); }